package jbeagle.concurrent.remote;

import java.rmi.Remote;
import java.rmi.RemoteException;
import java.util.concurrent.TimeUnit;

import jbeagle.core.FitnessFunction;
import jbeagle.core.Individual;

public interface ConcurrentEvaluationManager extends Remote {
	
	/**
	 * Get the next individual to evaluate. If there is currently no Individual to be
	 * evaluated (e.g. because the GeneticAlgorithm is busy doing other things, like
	 * producing the next generation), the method will cause the current thread to wait
	 * indefinitely until an Individual to evaluate becomes available. 
	 * 
	 * @return an Individual to evaluate
	 * @throws RemoteException
	 */
	Individual getNextToEvaluate() throws RemoteException;
	
	/**
	 * Same as {@link #getNextToEvaluate()}, except that this method causes the current
	 * thread to wait only as long as the specified wait time if an Individual is not yet
	 * available.
	 * 
	 * @return an {@code Individual} to evaluate, or {@code null} if no {@code Individual} became available
	 * within the specified wait time.
	 * @param timeout - how long to wait before giving up, in units of {@code unit}
	 * {@code unit} - a {@code TimeUnit} determining how to interpret the {@code timeout} parameter
	 * @throws RemoteException
	 */
	Individual pollNextToEvaluate(long timeout, TimeUnit unit) throws RemoteException;
	
	/**
	 * Check whether there will be more {@code Individual}s to evaluate. Note that there might
	 * not be any individuals at the moment (because the GeneticAlgorithm is busy
	 * doing other things, like producing the next generation). This method is only
	 * there to indicate that there will be more to evaluate in the future, so
	 * evaluator threads can use this to check if they should keep running.
	 * 
	 * @return {@code true} if there will be more {@code Individual}s to evaluate in the future.
	 * {@code false} if there is nothing more to evaluate (the genetic algorithm has finished or
	 * is about to finish).
	 * 
	 * @throws RemoteException
	 */
	boolean hasMoreToEvaluate() throws RemoteException;
	
	/**
	 * Tells the evaluation manager that {@code Individual} {@code ind} has been evaluated.
	 * 
	 * @param ind
	 * @throws RemoteException
	 */
	void setEvaluationComplete(Individual ind) throws RemoteException;
	
	Class<? extends FitnessFunction> getFitnessFunctionDef() throws RemoteException;
}
